package com.bfb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;

import com.bfb.adapters.DishAdapter;
import com.bfb.helpers.Dish;
import com.bfb.helpers.ListUtilities;
import com.bfb.helpers.ServerUtilities;
import com.customComponents.ImageText;
import com.customComponents.PromptDialog;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;

public class MatchDishes extends Activity {
	ArrayList<Dish> dishes = new ArrayList<Dish>();
	String msg = "";
	String input;
	JSONArray jsonArr = new JSONArray();
	String ingredients = "";
	private static final Facebook facebook = Main.facebook;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.match_dishes_view);
		new getDish().execute();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.game_menu, menu);
		menu.removeItem(R.id.clear_menuitem);
		menu.removeItem(R.id.match_dish_menuitem);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.share_facebook) {
			if (!Networking.isNetworkAvailable(getBaseContext())) {
				PromptDialog dlg = new PromptDialog(MatchDishes.this,
						R.string.internetConnectionPromptTitle,
						R.string.internetConnectionPromptMsgFB, false, -1,
						R.string.ok) {
					@Override
					public boolean onOkClicked() {
						return true;
					}
				};
				dlg.show();
			} else
				postOnWallAuthorize();

			return true;
		} else {
			return super.onOptionsItemSelected(item);
		}

	}

	/**
	 * This is the first step taken to post on a user's wall. In case
	 * authorization passes content is posted to the users wall.
	 */
	public void postOnWallAuthorize() {
		if (!facebook.isSessionValid())
			facebook.authorize(this, new String[] { "publish_stream" },
					new DialogListener() {
						@Override
						public void onComplete(Bundle values) {
							Main.user.setAllowFB(true);
							postToWall();
						}

						@Override
						public void onFacebookError(FacebookError error) {
							Toast.makeText(getBaseContext(),
									getString(R.string.fbError),
									Toast.LENGTH_LONG).show();
						}

						@Override
						public void onError(DialogError e) {
							Toast.makeText(getBaseContext(),
									getString(R.string.fbError),
									Toast.LENGTH_LONG).show();
						}

						@Override
						public void onCancel() {
						}
					});
		else
			postToWall();
	}

	/**
	 * Posts the user's wall on Facebook the image of the dish that matches the
	 * most with the dish he created. In case no matches were found the image
	 * with the sad face is posted. A list of the ingredients in the created
	 * dish are also posted with the image
	 */
	public void postToWall() {

		ServerUtilities.background(new Runnable() {
			@Override
			public void run() {

				try {
					Bundle params = new Bundle();
					ByteArrayOutputStream stream = new ByteArrayOutputStream();
					byte[] bitMapData;

					ImageText it = (ImageText) findViewById(R.id.highestMatch);
					ImageView iv = it.getImageView();

					Bitmap bitmap = ((BitmapDrawable) iv.getDrawable())
							.getBitmap();
					bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
					bitMapData = stream.toByteArray();
					params.putByteArray("picture", bitMapData);
					params.putString("message",
							"The message from android goes here");
					params.putString("caption",
							"The caption from android goes here");
					params.putString("description",
							"A description of the link from android goes here");
					params.putString("type", "photo");
					String ingredientsProcessed = ((ingredients.trim())
							.replaceAll(" ", ", ")).replaceAll("_", " ");
					params.putString(
							"name",
							"I created a dish with the following ingredients: "
									+ ingredientsProcessed
									+ " and this is the image of the dish that matches the most");
					params.putString("method", "post");

					facebook.request("me/photos", params, "POST");

				} catch (Exception e) {
					runOnUiThread(new Runnable() {

						@Override
						public void run() {
							Toast.makeText(getBaseContext(), "In exception",
									Toast.LENGTH_LONG).show();
						}
					});
				}
			}
		});
	}

	class getDish extends AsyncTask<Void, Void, String> {

		private ProgressDialog pdia;

		@Override
		protected void onPreExecute() {
			pdia = ProgressDialog.show(MatchDishes.this, "", getResources()
					.getString(R.string.searchMatchesLoader), true);
		}

		@Override
		public void onCancelled() {
			pdia.dismiss();
		}

		@Override
		protected void onPostExecute(String result) {
			Log.i("In Thread", "end loading");
			pdia.dismiss();
			Gallery gallery = (Gallery) findViewById(R.id.gallery1);

			gallery.setAdapter(new DishAdapter(getBaseContext(), gallery,
					dishes));
			gallery.setOnItemClickListener(((DishAdapter) gallery.getAdapter()).listener);

			// Retrieves the image of the dish in the first position i.e the
			// dish with the highest percentage of similarity. In case of an
			// exception, most probably bitmap array was empty an image is
			// displayed stating that no matches were found
			ImageText it = (ImageText) findViewById(R.id.highestMatch);
			if (dishes.size() == 0) {

				it.setResource(R.drawable.no_matches);

				it.setText(getResources().getString(R.string.noMatches));

			} else {
				Bitmap bitmap = dishes.get(0).getDishImage();
				if (bitmap == null)
					it.setResource(R.drawable.default_dish);
				else
					it.setBitmap(bitmap, 300, 200, true);

				it.setText(dishes.get(0).getDishName());

			}

		}

		@Override
		protected String doInBackground(Void... params) {

			try {
				HttpClient httpclient = new DefaultHttpClient();
				HttpPost httppost = new HttpPost("http://" + Main.SERVER
						+ "/match_dishes");
				// HttpPost httppost = new HttpPost(SERVER + "/match_dishes");
				Bundle type_ingredients = getIntent().getExtras();
				ingredients = type_ingredients.getString("ingredientNames");

				String dishType = type_ingredients.getString("dishTypeKey");

				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
						5);
				nameValuePairs.add(new BasicNameValuePair("ingredients",
						ingredients));

				nameValuePairs.add(new BasicNameValuePair("hateIngs",
						ListUtilities.listToString(Main.user.getHateIngs())));
				String neverShowValue = "";
				if (Main.user.getNeverShow())
					neverShowValue = "True";
				else
					neverShowValue = "False";
				nameValuePairs.add(new BasicNameValuePair("neverShow",
						neverShowValue));

				nameValuePairs.add(new BasicNameValuePair("userId",
						Main.android_id));
				nameValuePairs
						.add(new BasicNameValuePair("dishType", dishType));

				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

				// Execute HTTP Post Request
				HttpResponse response = httpclient.execute(httppost);

				/* Checking response */
				if (response != null) {
					HttpEntity entity = response.getEntity();

					// input = getContent(entity);
					input = ServerUtilities.getContentFromStream(entity
							.getContent());
					try {
						jsonArr = new JSONArray(input);
						dishes = new ArrayList<Dish>();
						for (int i = 0; i < jsonArr.length(); i++) {
							JSONObject current = jsonArr.getJSONObject(i);
							String details = current.getString("name")
									+ "\n%sim: "
									+ jsonArr.getJSONObject(i).getString(
											"percMatch") + '%';
							String dishKey = current.getString("key");
							// This try/catch is needed to avoid exceptions in
							// case an image was not saved for the dish and so
							// no "img" attribute was added to the JSON object
							try {

								ByteArrayInputStream is = new ByteArrayInputStream(
										Base64.decode(current.getString("img"),
												Base64.DEFAULT));
								Bitmap dishImage = BitmapFactory
										.decodeStream(is);
								dishes.add(new Dish(dishImage, details, dishKey));
							} catch (Exception e) {
								dishes.add(new Dish(null, details, dishKey));
							}
						}
					} catch (Exception e) {
						Log.e("Exception", input);
						runOnUiThread(new Runnable() {

							@Override
							public void run() {
								Toast.makeText(getBaseContext(),
										getString(R.string.serverError),
										Toast.LENGTH_LONG).show();
							}
						});
					}

				} else
					Log.e("respose_match_dishes", "response is null");
			} catch (Exception e) {
				e.printStackTrace();
				msg += e.toString();
				Log.e("Exception", msg);
				runOnUiThread(new Runnable() {

					@Override
					public void run() {
						Toast.makeText(getBaseContext(),
								getString(R.string.serverError),
								Toast.LENGTH_LONG).show();
					}
				});
			}
			return input;
		}
	}
}

/*
 * Some Resources:
 * http://stackoverflow.com/questions/3873515/add-description-to-
 * android-gallery-pictures-and-text
 * http://stackoverflow.com/questions/5667050/how
 * -to-display-image-from-bytearray-coming-from-webservice-in-android
 * http://mobiforge
 * .com/designing/story/understanding-user-interface-android-part-3-more-views
 * http://code.pui.ch/2007/07/23/python-sort-a-list-of-dicts-by-dict-key/
 * http://stackoverflow.com/questions/4435806/drawable-to-byte
 * http://www.anddev.
 * org/advanced-tutorials-f21/how-to-convert-bitmap-to-byte-array
 * -in-android-t12985.html
 * http://stackoverflow.com/questions/5168145/android-post
 * -picture-to-facebook-wall
 */
